/*
 *@Description: 追书神器爬取 小说菜单以及小说名
 *@Author:  lupan
 *@Date: 2019-06-19 19:46:13
*/
const http = require('http')
const fs = require("fs");
// nodejs生成UID（唯一标识符）——node-uuid模块
const UUID = require('uuid');
const {BookMenu, BookInfo} = require('../../db/model/index') 
const sourceUrl = 'http://www.zhuishushenqi.com/'
/*
 *@Description: 采集小说菜单
 *@params: 
 *@Author:  lupan
 *@Date: 2019-06-19 21:46:25
*/
const gatMenu = async (page) => {
  await page.click('.nav .container .nav-cells .nav-cell:nth-child(3) a')
  await page.waitFor(2000)
  await LOG.success('分类页面打开成功')
  const menu = await page.$$eval('.sort-cells .sort-cell', els => Array.prototype.slice.call(els).map(el => {
    return {
      menu: el.innerText,
      url: el.href,
      majorCode: el.href.split('major=')[1]
    }
  }))
  await LOG.success('一级菜单采集成功')
  const writeMenu = menu.map(item => {
    return {
      menu: item.menu,
      level: 1,
      majorCode: item.majorCode,
      parentCode: '-1',
      majorParentCode: '-1'
    }
  })
  const menuDB = await BookMenu.insertMany(writeMenu)
  await LOG.success('一级菜单写入成功')
  for (let i = 0; i < menu.length; i++) {
    await submenu(page, menu[i], menuDB[i])
  }
  await LOG.success('所有菜单写入成功...')
}

/*
 *@Description: 采集二级菜单
 *@params: 
 *@Author:  lupan
 *@Date: 2019-06-19 21:50:54
*/

const submenu = async (page, menu, menuDB) => {
  return new Promise(resolve => {
    (async() => {
      await page.goto(menu.url)
      await LOG.success(`${menu.menu}菜单打开成功，准备采集二级菜单...`)
      const submenu = await page.$$eval('.sub-sort-cells p .sub-sort-cell', els => Array.prototype.slice.call(els).filter(el => el.innerText !== '全部').map(el => {
        return {
          menu: el.innerText,
          majorCode: el.href.split('minor=')[1]
        }
      }))
      const writeSubMenu = submenu.map(item => {
        return Object.assign(item, {
          parentCode: menuDB._id,
          majorParentCode: menuDB.majorCode,
          level: 2
        })
      })
      const subMenuDB = BookMenu.insertMany(writeSubMenu)
      await LOG.success(`${menu.menu}二级菜单写入成功...`)
      resolve()
    })()
  })
}

/*
 *@Description: 采集小说信息
 *@params: 
 *@Author:  lupan
 *@Date: 2019-06-19 22:17:44
*/
const gatBookInfo = async (page, subMenu, pageNo) => {
  return new Promise(resolve => {
    (async () => {
      const url = `http://www.zhuishushenqi.com/category?gender=male&type=hot&major=${subMenu.majorParentCode}&minor=${subMenu.majorCode}&page=${pageNo}`
      await page.goto(url)
      await LOG.success(`${subMenu.menu}第${pageNo}页打开成功，准备采集...`)
      const bookData = await page.$$eval('.books-list a', els => Array.prototype.slice.call(els).map(el => {
        return {
          cover: el.children[0].src,
          title: el.children[1].children[0].children[0].innerText,
          author: el.children[1].children[1].children[0].innerText,
          info: el.children[1].children[2].innerText,
        }
      }))
      if (bookData.length === 0) {
        resolve(true)
      } else {
        bookData.map(item => {
          return Object.assign(item, {
            menuCode: subMenu._id,
            source: sourceUrl
          })
        })
        await LOG.success(`${subMenu.menu}第${pageNo}页小说信息采集成功`)
        // update 将保存为base64转为保存图片到服务器指定文件夹，实现接口访问图片

        // for (let i = 0; i < bookData.length; i++) {
        //   const coverBase64 = await gatImgToBase64(bookData[i].cover)
        //   bookData[i].cover = coverBase64
        // }
        for (let i = 0; i < bookData.length; i++) {
          const cover = await downloadImg(bookData[i].cover)
          bookData[i].cover = cover
        }
        await BookInfo.insertMany(bookData)
        await LOG.success(`${subMenu.menu}第${pageNo}页小说信息写入成功`)
        if (bookData.length < 20) {
          resolve(true)
        } else {
          await resolve(false)
        }
      }
    })()
  })
}

/*
 *@Description: 抓取网络图片转为base64
 *@params: 
 *@Author:  lupan
 *@Date: 2019-06-19 22:49:02
*/

const gatImgToBase64 = async (url) => {
  return new Promise(resolve => {
    http.get(url,function(res){
      const chunks = []; //用于保存网络请求不断加载传输的缓冲数据
      let size = 0;　　 //保存缓冲数据的总长度
      res.on('data',function(chunk){
        chunks.push(chunk);　 //在进行网络请求时，会不断接收到数据(数据不是一次性获取到的)，
        size += chunk.length;　　//累加缓冲数据的长度
      });
      res.on('end',function(err){
        const data = Buffer.concat(chunks, size);　　//Buffer.concat将chunks数组中的缓冲数据拼接起来，返回一个新的Buffer对象赋值给data
        const base64Img = data.toString('base64');　　//将Buffer对象转换为字符串并以base64编码格式显示
        resolve(`data:image/png;base64,${base64Img}`)
      });
    });
  })
}

/*
 *@name: 抓取网络图片保存到本地
 *@param:{type} 
 *@description:
 *@return:
 *@author: panlua
 *@date: 2019-06-25 09:03:41
*/
const downloadImg = (url) => {
  return new Promise(resolve => {
    http.get(url, res => {
      let imgData = ''
      res.setEncoding('binary') //一定要设置response的编码为binary否则会下载下来的图片打不开
      res.on('data', chunk => {
        imgData += chunk
      })
      res.on('end', () => {
        const coverId = UUID.v1()
        let route = `./bookCover/${coverId}.png`
        fs.writeFile(route, imgData, 'binary', err => {
          if (err) {
            LOG.error(`${url}________封面保存失败`, err)
            return false
          }
          LOG.success(`${url}________封面保存成功`)
          resolve(coverId)
        })
      })
    })
  })
}

const zssq = {
  gat: async (page) => {
    await page.goto(sourceUrl);
    await LOG.success('追书神器首页打开成功，即将采集...');
    const menuData = await BookMenu.find()
    if (!menuData.length) {
      await LOG.success('菜单未采集，准备采集')
      await gatMenu(page)
    }
    const subMenuData = await BookMenu.find({'level': 2})
    for(let i = 0; i < subMenuData.length; i++) {
      for (let j = 1; j < 51; j++) { // 追书神器最多查询50页
        const skip = await gatBookInfo(page, subMenuData[i], j)
        if (skip) {
          break;
        }
      }
    }
  }
}

export default zssq